/**
 * 这个js里的内容只是为了以后少写一些代码 毕竟autodesk 网站全英文看着贼费劲
 * 因为简化了许多内容，所以部分地方可能不如官网给的示例更灵活，是否使用看需求
 * 如果哪里写的有问题可以提意见，可以自行修改
 * https://aps.autodesk.com/en/docs/dataviz/v1/reference/DataVisualization/Room/    数据可视化  如精灵 热力图 等api
 * https://autodesk-forge.gitee.io/viewer-docs/                                     比较全的文档  包括event事件 及各个对象的内置属性方法等
 * https://aps.autodesk.com/en/docs/viewer/v7/reference/Viewing/EventUtils/         js sdk v7 的文档
 * author xhy 2023-02-08
 * **/

/**
 * localStorage 中的数据
 * 配置
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.optimizeNavigation            平滑导航 (开启后 导航期间响应更快 但质量下降)
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.ghosting                      隐藏对象略微可见 (显示隐藏对象的重影)
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.displayUnits                  显示单位
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.displayUnitsPrecision         显示精度
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.selectionMode                 选择模式 0: 叶对象  1: 第一个对象  2: 最后一个对象
 * 导航
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.alwaysUsePivot                cube 作用于轴 (不太懂，不过设置false后 cube操作比较麻烦)
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.orbitPastWorldPoles           动态观察世界极 (作用不明)
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.zoomTowardsPivot              禁用后缩放以当前光标位置为中心
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.reverseMouseZoomDir           反转鼠标方向 (滚轮放大缩小)
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.zoomScrollSpeed               鼠标滚轮灵敏度
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.zoomDragSpeed                 鼠标拖动灵敏度
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.leftHandedMouseSetup          交换鼠标上的按钮 (左右键事件互换)
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.clickToSetCOI                 鼠标左键 重设坐标中心点
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.openPropertiesOnSelect        选择对象时打开特性
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.bimWalkGravity                启用重力 (作用不明)
 * 外观
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.antialiasing                  抗锯齿
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.ambientShadows                环境遮挡阴影
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.groundShadow                  地面阴影
 * Autodesk.Viewing.Private.GuiViewer3D.SavedSettings.groundReflection              地面反射
 *
 * **/

/**
 * 常用Event列表   不全  需要去翻文档
 * 例：viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT,()=>{})
 * Autodesk.Explode  模型爆炸
 * Autodesk.DataVisualization.Core.MOUSE_CLICK  精灵点击事件
 * Autodesk.SELECTION_CHANGED_EVENT    选择更改事件,构件点击时会触发
 * **/

/**
 * 创建GuiViewer3D
 * element         dom节点
 * **/
export function createGuiViewer3D(element) {
  return new window.Autodesk.Viewing.Private.GuiViewer3D(element, {
    extensions: [
      "Autodesk.Viewing.ZoomWindow"
    ],
    disabledExtensions: {
      measure: false,
      section: false,
    },
    memory: {
      limit: 32 * 1024    //32 GB
    }
  });
}

/**
 * 获取构建数据
 * viewer         viewer对象
 * nodeArray      构件点击事件可以获取
 * **/
export function getNodeData(viewer, nodeArray) {
  let tree = viewer.model.getData().instanceTree;
  let nodeData = {};
  if (nodeArray.length !== 0) {
    let selectedNode = nodeArray[0];
    nodeData.ID = selectedNode;
    nodeData.Name = tree.getNodeName(selectedNode);
    nodeData.Parent = tree.getNodeName(tree.getNodeParentId(selectedNode));
    let result = {
      fragId: [],
      matrix: [],
    };
    tree.enumNodeFragments(nodeArray[0], function (frag) {
      let fragProxy = viewer.impl.getFragmentProxy(viewer.model, frag);
      let matrix = new window.THREE.Matrix4();
      fragProxy.getWorldMatrix(matrix);
      result.fragId.push(frag);
      result.matrix.push(matrix);
    });
    // continue if it has transformation Matrix (meaning it is not a "group node")
    if (result) {
      nodeData.position = result.matrix[0].getPosition();
    } else {
      nodeData.position = new window.THREE.Vector3();
    }
    return nodeData
  }


}

/**
 * 视角锁定 / 解除
 * viewer         viewer对象
 * lock           是否锁定 boolean
 * **/
export function navigationLock(viewer,lock) {
  viewer.setNavigationLock(lock)
}

/**
* 新增引线
 * viewer             viewer对象
 * options.color       new THREE.Color(0x000000)对象实例  或者{r: 0,g: 0,b: 0}
 * options.points      数组[1,1,1,2,2,2]  每3个数代表一个xyz坐标点
 * options.lineWidth   线粗
 * options.opacity     线透明度
* */
export async function createStreamLineSpecs(viewer,options) {
  const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
  const streamLineData = {
    points: new Float32Array(options.points),
  };
  const streamLineSpecs = {
    lineWidth: options.lineWidth || 5,
    lineColor: options.color,
    opacity: options.opacity || 1,
    lineData: streamLineData,
  };
  return dataVizExtn.streamLineBuilder.createStreamLine(streamLineSpecs);
}

/**
 * 删除引线
 * viewer       viewer对象
 * line         StreamLine对象
 * */
export async function destroyStreamLine(viewer,line) {
  const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
  dataVizExtn.streamLineBuilder.destroyStreamLine(line);
}

/**
 * 新增精灵
 * viewer                 viewer对象
 * autoDesk               autoDesk对象
 * options.dbId           精灵id，后续通过id操作精灵
 * options.img            精灵图片,可以是网络地址  也可以是base64
 * options.size           精灵大小
 * options.data           精灵坐标数组  如[{position: {x: 0,y:0,z:0}}]
 * **/
export async function createSprite(viewer,options) {
  const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
  const DataVizCore = window.Autodesk.DataVisualization.Core;
  const viewableType = DataVizCore.ViewableType.SPRITE;
  const spriteIconUrl = options.img;
  const style = new DataVizCore.ViewableStyle(viewableType, {r:1,g:1,b:1}, spriteIconUrl);
  const viewableData = new DataVizCore.ViewableData();
  viewableData.spriteSize = options.size || 24; // Sprites as points of size 24 x 24 pixels
  const myDataList = options.data;
  myDataList.forEach(myData => {
    const position = myData.position;
    const viewable = new DataVizCore.SpriteViewable(position, style, options.dbId);
    viewableData.addViewable(viewable);
    //  viewableData.viewables 可以查看当前已有精灵
  });
  await viewableData.finish();
  dataVizExtn.addViewables(viewableData);
}

/**
 * 修改精灵坐标（移动精灵）
 * viewer                 viewer对象
 * spriteArray            精灵数组
 * sprite.dbId            精灵id
 * sprite.position        精灵坐标对象,如 {x: 0,y:0,z:0}
 * **/
export async function moveSprite(viewer,spriteArray){
  const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
  spriteArray.forEach(sprite=>{
    dataVizExtn.invalidateViewables([sprite.dbId], (viewable) => {
      return {
        // Move the viewable to a new location.
        position: sprite.position
      };
    })
  })
}

/**
 * 删除全部精灵
 * **/
export async function removeAllViewables(viewer){
  const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
  dataVizExtn.removeAllViewables()
}

/**
 * 3d坐标转2d
 * viewer                 viewer对象
 * position               三维坐标 {x: 0,y: 0,z: 0}
 * **/
export function coordinateTranslate(viewer,position) {
  // console.log('xy ____________________ ',window,window.innerWidth,window.innerHeight)
  let p = new window.THREE.Vector3(position.x, position.y, position.z).project(viewer.impl.camera)
  let x = ((p.x + 1) / 2 * window.innerWidth) + 'px';
  let y = (-(p.y - 1) / 2 * window.innerHeight) + 'px';
  return {
    x,y
  }
}

/**
 *
 * **/
